<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Abort Fetch Stream</title>
</head>

<body>
<button id="startButton">开始流式传输</button>
<button id="abortButton">停止流式传输</button>
<pre id="output"></pre>
<script>
    const startButton = document.getElementById('startButton');
    const abortButton = document.getElementById('abortButton');
    const output = document.getElementById('output');

    let controller;
    let reader;

    startButton.addEventListener('click', async () => {
        controller = new AbortController();
        const signal = controller.signal;
        abortButton.disabled = false;
        startButton.disabled = true;

        let obj = {
            "model": "deepseek-r1:8b",
            "prompt": "如何学习AI算法",
            "stream": true
        }
        try {
            const response = await fetch('http://localhost:11434/api/generate', {
                signal,
                method: 'POST',
                body: JSON.stringify(obj)
            });


            reader = response.body.getReader();

            while (true) {
                const {done, value} = await reader.read();
                if (done) {
                    console.log('done流已关闭');
                    break;
                }
                const text = new TextDecoder().decode(value);
                const chunk = JSON?.parse(text.replace('data:', ''))
                output.textContent += chunk.response;
            }
        } catch (error) {
            if (error.name === 'AbortError') {
                output.textContent += '\n\n流式传输已停止';
            } else {
                output.textContent += `\n\n发生错误: ${error.message}`;
            }
        } finally {
            abortButton.disabled = true;
            startButton.disabled = false;
        }
    });

    abortButton.addEventListener('click', () => {
        console.log(reader)
        // 主动取消流
        reader.cancel('用户主动取消').then(() => {
            // 清理资源
            reader.releaseLock();
            console.log('流已关闭', reader);
        });

        // if (controller) {
        //     controller.abort();
        // }
    });
</script>
</body>

</html>